/*
 * Assembler.java
 *
 * Created on 13. Juni 2007, 11:50
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package sbc;

import java.util.*;
import corso.lang.*;
import sbc.corso.*;
import sbc.corso.Sensor;
import sbc.corso.SensorConsumer;
import sbc.corso.util.*;

import sbc.fact.*;
import sbc.factory.SensorFeature;

/**
 *
 * @author mustermark
 */
public class Assembler extends Worker {
    
    private String name;
    private CorsoVarOid inspectedChannelOid, unitChannelOid;
    private CorsoConstOid  boardPipeOid;
    
    //private CorsoPipe uninspectedSensorChannel;
    //private CorsoPipe inspectedSensorChannel;
    
    /*public void read (CorsoData data) throws CorsoDataException {
        StringBuffer structName = new StringBuffer ();

        int arity = data.getStructTag (structName);
        if (arity != 1) {
          System.out.println ("arity = " + arity);
          throw new CorsoDataException ();
        }
        //number = data.getInt ();
        if(!structName.toString().equals("SensorOid")) {
               System.out.println ("unknown struct: " + structName);
            throw new CorsoDataException ();
        }
            
        
        oid = new CorsoVarOid();
        data.getShareable(sensorOid);
        
     }

    public void write (CorsoData data) throws CorsoDataException {
        data.putStructTag ("SensorOid", 1);
        data.putShareable(sensorOid);
        //data.putShareable (nextOid);
    }*/

    
    public Assembler() {
        super();
        //oid = new CorsoVarOid();
    }
    /**
     * Creates a new instance of Assembler
     */
    public Assembler(String n) {
        this();
        name = n;
        
        /*CorsoVarOid uninspectedSensorChannelOid = new CorsoVarOid();
        //CorsoVarOid inspectedSensorChannelOid = new CorsoVarOid();
        try {
            uninspectedSensorChannelOid = con.getNamedVarOid("uninspectedSenors", site, null, false, CorsoConnection.NO_TIMEOUT);
            //inspectedSensorChannelOid = con.getNamedConstOid("inspectedSenors", site, null, false, CorsoConnection.NO_TIMEOUT);
        } catch(CorsoException e) {
            System.out.println("Couldn't retrieve sensor channels for: " +n);
            System.out.println(e);
            System.out.println(e.getMessage());
            System.exit(-10);
            //throw new BridgeException();

        }*/
        
        // create the channel object ********************************************
        //uninspectedSensorChannel = new CorsoPipe(uninspectedSensorChannelOid);
        //inspectedSensorChannel = new CorsoPipe(inspectedSensorChannelOid);
        /*System.out.println("Channels created:");
        System.out.println(uninspectedSensorChannel);
        System.out.println(inspectedSensorChannel);*/
        boardPipeOid = new CorsoConstOid();
        inspectedChannelOid = new CorsoVarOid();
        unitChannelOid = new CorsoVarOid();
        try {
            inspectedChannelOid = con.getNamedVarOid("inspectedSensors", site, null, false, CorsoConnection.NO_TIMEOUT);
            unitChannelOid = con.getNamedVarOid("units", site, null, false, CorsoConnection.NO_TIMEOUT);
            boardPipeOid = con.getNamedConstOid("boards", site, null, false, CorsoConnection.NO_TIMEOUT);
        } catch(Exception e) {
            System.out.println("error getting sensorchannel...");
            e.printStackTrace();
            
        } 
        
        
        SensorConsumer sensorConsumer = new SensorConsumer(this, inspectedChannelOid);
        sensorConsumer.start();
        
        /*Runnable sensorCatcher = new Runnable() {
            public void run() {
                for (;;) {
                    String name =null;
                    try {
                        CorsoVarOid oid = uninspectedSensorChannel.next();
                        
                        //materialStreamNames.add();
                        
                    } catch(CorsoException e) {
                        System.out.println("Couldn't retrieve rawMaterialStream for Factory: " +name);
                        System.out.println(e);
                    }   
                    
                }
            }
        };
        Thread catcherThread = new Thread(boardAndSensorCatcher);
        catcherThread.start();*/
        
        /*try {
            oid = con.createVarOid(con.getCurrentStrategy());
            //sensorOid.writeString(education, CorsoConnection.NO_TIMEOUT);
            //sensorOid.writeShareable(new Sensor(), CorsoConnection.NO_TIMEOUT);
            workChannel.append(oid);
        
        } catch(CorsoException e) {
            System.out.println("Error wrinting sensorOid to " + workChannel);
            System.out.println(e);
        }*/
            
        
        /*try {
            CorsoConstOid rawMaterialOid = con.getOrCreateNamedConstOid (con.getCurrentStrategy(), name, null);
            final RawMaterialStream rawMaterial = new RawMaterialStream(rawMaterialOid);
            Runnable rawMaterialLine = new Runnable() {
                public void run() {
                    for (;;) {
                        try {
                            Module mod = rawMaterial.readNextModule();
                            System.out.println ("New data: " + mod);
                            //moduleQueque.add(mod);
                            if(mod instanceof Sensor) {
                                //uninspectedSensorQueque.add((Sensor)mod);

                            } else if(mod instanceof Board) {
                               // boardQueque.add((Board)mod);
                            } else {
                                System.out.println("Unknown RawMaterial");
                            }
                        } catch(Exception e) {
                            System.out.println("Error getting next Module ");
                            System.out.println(e);
                        }
                        
                    }
                }
            };
            Thread rawMaterialLineThread = new Thread(rawMaterialLine);
            rawMaterialLineThread.start();
            System.out.println ("rawmaterialline for " + name + " established!");

        } catch(Exception e) {
            System.out.println("Error creating MaterialStream");
            System.out.println(e);
        }*/
        
        
        /*Vector users = new Vector ();
        users.addElement (new String ("*"));
        try {
            // create new service types ********************************************
            con.addServiceType ("InspectionExecutionService", "SensorInspection", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'InspectionExecutionService' created ");
            con.addServiceType ("AssemblyExecutionService", "UnitAssembly", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'AssemblyExecutionService' created ");
            con.addServiceType ("DeliveryExecutionService", "UnitDelivery", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'DeliveryExecutionService' created ");

        } catch(Exception e) {
            System.out.println("Error adding Service Types ");
            System.out.println(e);
        }
        */
        //Thread inspectionThread = new Thread(new InspectionExecution());
        //inspectionThread.start();
        
        
    }
    
    //static Sensor tmpSensor = null;
    
    public void workOn(CorsoShareable sh) {
        Sensor s = (Sensor)sh;
        CorsoTopTransaction tx = null;
        
        try {
            tx = con.createTopTransaction ();
        } catch(CorsoException e) {
            System.out.println("Couldn't create TopTransaction");
            System.out.println(e);
        }
        System.out.println("starting INSPECTED SensorTransaction");
        
        //Sensor s = new Sensor(oid, tx);
        //SensorChannel uninspectedSensorChannel = new SensorChannel(uninspectedChannelOid);            
        
        if(!s.isInspected()) {
            try {
                tx.abort ();
                System.out.println("Transaktion aborted - invalid EDUCATION");
                
            } catch(CorsoException e) {
                System.out.println(e);
            }
        } else {//if(tmpSensor == null) {
            //tmpSensor = s;
            try {
                SensorChannel channel = new SensorChannel(inspectedChannelOid);
                System.out.println("wainting for another Sensor....");
                SensorLinker linker = channel.readNextModuleLinker();
                Sensor second = linker.sensor;
                System.out.println("retrieved second Sensor....: " + second);
                if(!second.isInspected()) {
                    System.out.println("Found uninspected Sensor " + second + " - cancelling assembly");
                    tx.abort();
                }
                //calledTwice = true;
                try {
                    System.out.println("Trying to retrieve baord for Assembly...");
                    CorsoPipe boardPipe = new CorsoPipe(boardPipeOid);            
                    Board b = (Board)boardPipe.next();
                    System.out.println("Board retrieved!!!");
                    UnitChannel unitChannel = new UnitChannel(unitChannelOid);
                    Unit unit = new Unit(b, s, second);
                    //Sensor s = new Sensor(id, features);
                    UnitLinker uLinker = new UnitLinker();
                    uLinker.unit = unit;
                    uLinker.next = con.createConstOid (con.getCurrentStrategy());
                    unitChannel.appendModuleLinker(uLinker);
                    System.out.println("appended UNIT" + uLinker.unit + " to UnitChannel");
                } catch(Exception e) {
                    System.out.println("Error retrieving Board");
                    e.printStackTrace();
                }
                
            } catch(Exception e) {
                e.printStackTrace();
                System.out.println("Couldn't retrieve Oid from channel");
                System.out.println("Waiting 10 sec...");
                try { Thread.currentThread().sleep(10000); }
                catch(Exception ex) {}
                
            }   
        } /*else {
            System.out.println("READY TO ASSEMBLE A UNIT!!!");
            calledTwice = false;
            try {
                
                CorsoPipe boardPipe = new CorsoPipe(boardPipeOid);            
                Board b = (Board)boardPipe.next();
                System.out.println("Board retrieved!!!");
            } catch(Exception e) {
                System.out.println("Error retrieving Board");
                e.printStackTrace();
            }
            
        }*/
        //SensorChannel inspectedSensorChannel = new SensorChannel(inspectedChannelOid);            
        //System.out.println("Edu: "+education.toString());
        
    }
    
    
    /*JobApplicationNotifier inspectorApplicationNotifier = new JobApplicationNotifier("InspectorApplication", site, con, 
            new JobApplicationReceiver(){
                public void shareableRegistered(CorsoShareable shareable) {
                    Registration reg = (Registration)shareable;
                    reg.getApplicant();
                    reg.getEducation();
                }
                public void objectModified(CorsoShareable shareable) {
                    CorsoVarOid oid = (CorsoVarOid)shareable; 
                    //CorsoData data = con.createData();
                    
                    
                }
            }
    ) {
        protected CorsoVarOid createEmptyShareable() {
            oid = new CorsoVarOid();
            return oid;
        }
    };*/
    static int cnt;
    
    public static void main (String [] args) {
        if (args.length == 1) {
            Assembler i = new Assembler(args[0]);
            
            //System.exit (-1);
        } else {
            System.out.println ("CALL: Assembler <name>");
            
            Assembler i = new Assembler("Assembler0");
            System.out.println ("strating test instance: Assembler0");
        }

        
        //f.open();
    }
}
